import Map from 'ol/Map'
import { ref } from 'vue'

/**
 * 将地图导出为PNG图片
 * @param map OpenLayers地图实例
 * @param options 导出选项
 * @returns Promise<string> 返回base64格式的图片数据
 */
export const MapExporterToPNG = async (
  map: Map,
  options: {
    pixelRatio?: number
    width?: number
    height?: number
    filename?: string
  } = {}
): Promise<string> => {
  return new Promise((resolve, reject) => {
    map.once('rendercomplete', () => {
      const {
        pixelRatio = 1,
        filename = 'map-export.png'
      } = options

      const mapSize = map.getSize();
      if (!mapSize) {
          reject(new Error('无法获取地图尺寸'));
          return;
      }

      const width = Math.round(options.width ?? mapSize[0]);
      const height = Math.round(options.height ?? mapSize[1]);

      // 步骤 1: 创建一个逻辑尺寸的中间 Canvas
      const intermediateCanvas = document.createElement('canvas');
      intermediateCanvas.width = width;
      intermediateCanvas.height = height;
      
      const intermediateContext = intermediateCanvas.getContext('2d');

      if (!intermediateContext) {
        reject(new Error('无法创建中间 Canvas 上下文'));
        return;
      }

      intermediateContext.fillStyle = '#111';
      intermediateContext.fillRect(0, 0, intermediateCanvas.width, intermediateCanvas.height);

      // 将每个 OpenLayers 图层 Canvas 绘制到中间 Canvas 上
      map.getViewport().querySelectorAll<HTMLCanvasElement>('.ol-layer canvas, canvas.ol-layer').forEach((canvas) => {
        if (canvas.width > 0) {
          intermediateContext.save();

          const opacity = canvas.parentNode instanceof HTMLElement ? (canvas.parentNode.style.opacity || canvas.style.opacity) : canvas.style.opacity;
          intermediateContext.globalAlpha = opacity === '' ? 1 : Number(opacity);
          
          let matrix: number[];
          const transform = canvas.style.transform;
          if (transform) {
            const match = transform.match(/^matrix\(([^)]+)\)$/);
            if (match && match[1]) {
              matrix = match[1].split(',').map(Number);
            } else {
                matrix = [1, 0, 0, 1, 0, 0]; // 备用值
            }
          } else {
              // 当没有 transform 样式时，计算从客户端（逻辑）尺寸到 Canvas（物理）尺寸的缩放比例
              // OpenLayers 内部渲染已隐式处理设备像素比。
              const scaleX = canvas.clientWidth / canvas.width;
              const scaleY = canvas.clientHeight / canvas.height;
              matrix = [scaleX, 0, 0, scaleY, 0, 0];
          }

          // 将图层的内部变换矩阵应用到中间 Canvas 的上下文
          // @ts-ignore: TypeScript 可能无法识别 apply 方法的此重载，但运行时行为是正确的。
          CanvasRenderingContext2D.prototype.setTransform.apply(intermediateContext, matrix);
          
          const backgroundColor = canvas.parentNode instanceof HTMLElement ? (canvas.parentNode.style.backgroundColor || canvas.style.backgroundColor) : '';
          if (backgroundColor) {
            intermediateContext.fillStyle = backgroundColor;
            intermediateContext.fillRect(0, 0, canvas.width, canvas.height); 
          }
          intermediateContext.drawImage(canvas, 0, 0);
          
          intermediateContext.restore();
        }
      });

      intermediateContext.globalAlpha = 1;
      // 在所有图层绘制到中间 Canvas 后，重置全局变换，确保 toDataURL 操作在一个干净的上下文中进行
      intermediateContext.setTransform(1, 0, 0, 1, 0, 0);

      let finalDataUrl: string;

      // 步骤 2: 如果指定了 pixelRatio，则处理最终导出
      if (pixelRatio !== 1) {
        const finalExportCanvas = document.createElement('canvas');
        finalExportCanvas.width = width * pixelRatio;
        finalExportCanvas.height = height * pixelRatio;
        const finalExportContext = finalExportCanvas.getContext('2d');
        if (finalExportContext) {
          finalExportContext.drawImage(intermediateCanvas, 0, 0, finalExportCanvas.width, finalExportCanvas.height);
          finalDataUrl = finalExportCanvas.toDataURL('image/png');
        } else {
          reject(new Error('无法创建最终导出 Canvas 上下文'));
          return;
        }
      } else {
        finalDataUrl = intermediateCanvas.toDataURL('image/png');
      }

      // 下载最终图片
      const link = document.createElement('a');
      link.download = filename;
      link.href = finalDataUrl;
      link.click();

      resolve(finalDataUrl);

    });
    map.renderSync();
  });
}

const isFullScreenRef = ref(false);

/**
 * 切换地图全屏模式
 * @param mapElement 地图容器的HTMLElement引用
 */
export function toggleFullScreen(mapElement: HTMLElement | null) {
  if (!mapElement) return;

  if (document.fullscreenElement) {
    document.exitFullscreen();
  } else {
    mapElement.requestFullscreen();
  }
}

/**
 * 旋转地图视图
 * @param map OpenLayers地图实例
 */
export function rotateMap(map: Map) {
  if (!map) return;
  const view = map.getView();
  const currentRotation = view.getRotation();
  view.setRotation(currentRotation + Math.PI / 4); // 每次旋转45度
}

/**
 * 监听全屏状态变化并更新响应式引用
 */
export function watchFullScreen(mapElement: HTMLElement | null) {
  const updateFullScreenStatus = () => {
    isFullScreenRef.value = !!document.fullscreenElement;
  };

  // 初始检查
  updateFullScreenStatus();

  document.addEventListener('fullscreenchange', updateFullScreenStatus);

  // 返回一个函数用于清理事件监听器
  return () => {
    document.removeEventListener('fullscreenchange', updateFullScreenStatus);
  };
}

export { isFullScreenRef as isFullScreen }; 